home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Tcl / Modes / tclMode.tcl < prev    next >
Encoding:
Text File  |  2001-02-02  |  44.7 KB  |  498 lines

  1. ## -*-Tcl-*-
  2.  # # ###################################################################
  3.  #  Alpha - new Tcl folder configuration
  4.  # 
  5.  #  FILE: "tclMode.tcl"
  6.  #                                    created: 5/4/97 {9:31:10 pm} 
  7.  #                                last update: 02/02/2001 {17:48:49 PM} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <vince@santafe.edu>
  10.  #    mail: 317 Paseo de Peralta
  11.  #          Santa Fe, NM 87501, USA
  12.  #     www: <http://www.santafe.edu/~vince/>
  13.  #  
  14.  # Copyright (c) 1997-2000 Vince Darley
  15.  #  
  16.  # Three procs from original: Tcl::DblClick listArray, getVarValue
  17.  #    
  18.  # Adds support for Tk, Itcl keywords and completions, plus 
  19.  # numerous fixes, improvements and integration with Vince's
  20.  # Additions.
  21.  # ###################################################################
  22.  ##
  23.  
  24. alpha::mode Tcl 1.9.3 tclMenu [list *.tcl *.itcl *.itk *.decls *.msg \
  25.   *.tbc tclIndex* "\\* Trace '*' \\*" *.test] {
  26.     tclMenu electricTab electricReturn electricBraces alphaDeveloperMenu
  27. } {
  28.     addMenu tclMenu "•269" "Tcl" "Tcl menu\r\rnot very obvious..."
  29.     set unixMode(wish) {Tcl}
  30.     set unixMode(tclsh) {Tcl}
  31.     set unixMode(itclsh) {Tcl}
  32.     set unixMode(itkwish) {Tcl}
  33.     set unixMode(prowish) {Tcl}
  34.     set unixMode(protclsh) {Tcl}
  35.     set unixMode(tclkit) {Tcl}
  36.     newPref sig tclshSig "WIsH"
  37.     ensureset evaluateRemotely 0
  38.     trace variable evaluateRemotely w tcltk::evaluateRemoteSynchronise
  39.     menu::buildProc tclMenu menu::buildtclMenu
  40.     lappend tclCmdColourings Tcl::colorTclKeywords \
  41.       Tcl::colorTkKeywords \
  42.       Tcl::colorItclKeywords Tcl::colorPseudoTclKeywords \
  43.       Tcl::colorTkCommands 
  44.     lappend tclExtraColourings \
  45.       Tcl::colorSymbols Tcl::colorMagicStrings
  46. } maintainer {
  47.     "Vince Darley" vince@santafe.edu <http://www.santafe.edu/~vince/>
  48. } uninstall this-file help {
  49.     This mode is for editing Tcl code.  You can edit code for internal
  50.     use with Alpha, or use Alpha as an external editor for code destined
  51.     for use with Tcl and Tk interpreters --- <http://www.tcltk.com>
  52.     distributes the Tclsh/Wish applications and a tcl-tk browser plugin.
  53.     <http://www.scriptics.com/> maintains a Tcl Developer's Xchange, and
  54.     is the best source for the latest Tcl/Tk releases.
  55.  
  56.     Most of Alpha(tk)'s functionality is contained in its Tcl library.  See
  57.     the "Tcl Example.tcl" file for an example.  You can 'evaluate' a
  58.     procedure (or any Tcl code for that matter) to make changes on the
  59.     fly.  If you select 'Evaluate Remotely' in the tcl-tk submenu, then
  60.     such actions will actually send the code to a separately running
  61.     Tclsh/Wish application to be evaluated.
  62.     
  63.     Alternatively, you can add .tcl files you wish to run in remote
  64.     interpreters to the tcl-tk submenu.  Selecting them will startup
  65.     a remote shell, source that .tcl file into it, and put Alpha(tk)
  66.     into 'remote' mode. Subsequent loading of code will go to the
  67.     remote shell automatically, so you can use Alpha to edit and
  68.     reload procedures in the remote shell, very simply.
  69.  
  70.     Alpha includes the help files "Tcl Commands", and "Tcl Resources".
  71. }
  72.  
  73. namespace eval tcltk {}
  74. proc tclMenu {} {}
  75.  
  76. # ◊◊◊◊ menu and prefs ◊◊◊◊ #
  77. # The menu.
  78. proc menu::buildtclMenu {} {
  79.     global tclMenu evaluateRemotely tcltk::executables
  80.     set execs {}
  81.     if {[info exists tcltk::executables]} {
  82.     lappend execs "\(-"
  83.     foreach ex ${tcltk::executables} {
  84.         lappend execs [file tail $ex]
  85.     }
  86.     }
  87.     set ma [list \
  88.       "/Levaluate" "/-<UswitchToTclsh" \
  89.       [list Menu -n "tcl-tk" -p tcltk::menuProc [concat [list \
  90.       "![lindex {{ } •} $evaluateRemotely]evaluateRemotely" \
  91.       executeCommand executeFileInRemoteShell addWindowToListOfExecutables] \
  92.       $execs]] \
  93.       "\(-" "/L<O<BreloadProc" "/I<O<BreformatProc" \
  94.       "rebuildTclIndexForWin" "debugProc" "applyChanges" "\(-" \
  95.       "<U/PfindProcDefinition…" "/Q<IquickFindProc…" "getVarValue…" \
  96.       "/4<BaddRemoveDollars" "/3<BinsertDivider" \
  97.       "\(-" "regularExpressionColors" "defaultColors"]
  98.     return [list build $ma Tcl::MenuProc "" $tclMenu]
  99. }
  100. menu::buildSome tclMenu
  101.  
  102. #===============================================================================
  103. #
  104. # Set up package-specific mode variables
  105.  
  106. # Removing obsolete preferences from earlier versions.
  107. prefs::removeObsolete TclmodeVars(alphaKeyWordColor) TclmodeVars(keywordColor) \
  108.   TclmodeVars(tclHelp)
  109.  
  110. newPref v prefixString {# } Tcl
  111. newPref f wordWrap {0} Tcl
  112. newPref v funcExpr {^proc *([-+a-zA-Z0-9:]+)} Tcl
  113. newPref v parseExpr {^proc *([-+a-zA-Z0-9:]+)} Tcl
  114. newPref v wordBreak {(\$)?[\w:_]+} Tcl
  115. newPref v wordBreakPreface {([^\w:_\$]|.\$)} Tcl
  116. newPref f autoMark 0 Tcl
  117. # Indentation scheme for lines following one ending in a backslash
  118. newPref v indentSlashEndLines 1 Tcl "" indent::amounts varindex
  119. # Mark files structurally, recognising the special comments
  120. # entered by 'ctrl-3'
  121. newPref f structuralMarks 0 Tcl
  122. # Cmd-double-clicking on a Tcl command will provide web-based documentation
  123. # from this location.
  124. newPref url tclHelpLocation "http://dev.scriptics.com/man/tcl8.4/TclCmd/" Tcl
  125.  
  126. newPref v procSearchPath "" Tcl
  127.  
  128. newPref f structuralElectricElseBrace 0 Tcl
  129.  
  130. set Tcl::startPara {^(.*\{)?[ \t]*(#|$)}
  131. set Tcl::endPara {^(.*\})?[ \t]*(#|$)}
  132. set Tcl::commentRegexp {^[ \t]*#}
  133.  
  134. # Not sure if this is used by completions still...
  135. set Tclcmds { append array catch close concat continue elseif error
  136. for foreach format lindex llength lrange lreplace lsearch lsort regexp 
  137. regsub rename return string switch while }
  138.  
  139. #===============================================================================
  140. #
  141. # Colorization setup
  142. #
  143.  
  144. # Colour Tk commands
  145. newPref f recogniseTk        {1}    Tcl    {Tcl::updateColors}
  146. # Colour [incr Tcl] commands
  147. newPref f recogniseItcl        {1}    Tcl    {Tcl::updateColors}
  148. # Recognise and colour some common procedures 'lunion' etc.
  149. newPref f recognisePseudoTcl    {1}    Tcl    {Tcl::updateColors}
  150. # Colour of all chosen commands.
  151. newPref color commandColor        {blue}    Tcl    {Tcl::updateColors}
  152. # Color for Tcl comments
  153. newPref color commentColor        {red}    Tcl    {Tcl::updateColors}
  154. # In Tcl, the colour of words started by '$'.  Tcl considers such 
  155. # words to be variables.  A dark brown might be a good choice, 
  156. # distinguishable, but not too distracting.  To try that, chose 
  157. # 'Config:Redefine Colors:Color_9' and set it to brown (the 'raw sienna'
  158. # crayon is a good choice). Then, when you are done, come back
  159. # to this dialog. Color_9 will now be available as a choice.
  160. newPref color magicColor        {black}    Tcl    {Tcl::updateColors}
  161. # Colour for strings
  162. newPref color stringColor        {green}    Tcl    {Tcl::updateColors}
  163. # Colour of symbols such as \, -, +, *, etc.  Can be useful for
  164. # reading regular expressions.
  165. newPref color symbolColor        {black}    Tcl    {Tcl::updateColors}
  166.  
  167. ## 
  168.  # -------------------------------------------------------------------------
  169.  # 
  170.  # "Tcl::_updateKeywords" --
  171.  # 
  172.  #  This proc now includes support for optional separate colorization of 
  173.  #  alpha commands. To use, set 'alphaKeyWordColor' to something other than 
  174.  #  'none' in the Tcl Mode Preferences dialog. -trf
  175.  # -------------------------------------------------------------------------
  176.  # 
  177.  # Now split into a series of procs, called in the end by colorizeTcl.  -cbu
  178.  # 
  179.  # -------------------------------------------------------------------------
  180.  ##
  181.  
  182. #===============================================================================
  183. #
  184. # Color procs begin here #
  185. #
  186.  
  187.  
  188. #===============================================================================
  189. #
  190. # Color Tcl Keywords
  191. #
  192.  
  193. proc Tcl::colorTclKeywords {} {
  194.     global TclmodeVars
  195.  
  196.     # all except beep and echo are basic Tcl keywords
  197.  
  198.     set tclKeyWords {
  199.     after append array auto_execok auto_import auto_load
  200.     auto_load_index auto_qualify beep binary break case catch cd clock
  201.     close concat continue dde default echo else elseif encoding eof
  202.     error eval exec exit expr fblocked fconfigure fcopy file
  203.     fileevent flush for foreach format gets glob global history if
  204.     incr info interp join lappend lindex linsert list llength load
  205.     lrange lreplace lsearch lsort namespace open package pid
  206.     pkg_mkIndex proc puts pwd read regexp regsub rename resource
  207.     return scan seek set socket source split string subst switch
  208.     tclLog tclMacPkgSearch tclPkgSetup tclPkgUnknown tell time
  209.     trace unknown unset update uplevel upvar variable vwait while
  210.     }
  211.     
  212.     regModeKeywords -a                \
  213.       -e {#} -c $TclmodeVars(commentColor)      \
  214.       -s $TclmodeVars(stringColor)              \
  215.       -k $TclmodeVars(commandColor) Tcl      \
  216.       $tclKeyWords 
  217.  
  218. }
  219.  
  220.  
  221.  
  222.  
  223. #===============================================================================
  224. #
  225. # Color Tk Keywords
  226. #
  227.  
  228. proc Tcl::colorTkKeywords {} {
  229.     global TclmodeVars
  230.  
  231.     set tkKeyWords {
  232.     bell bind bindtags button canvas checkbutton console destroy
  233.     entry event focus font frame grab grid image label listbox menu
  234.     menubutton message pack place radiobutton raise scale scrollbar
  235.     text tk tkwait toplevel winfo wm
  236.     }
  237.  
  238.     if {$TclmodeVars(recogniseTk)} {
  239.      regModeKeywords -a             \
  240.       -k $TclmodeVars(commandColor) Tcl    \
  241.       $tkKeyWords
  242.     } else {
  243.      regModeKeywords -a             \
  244.       -k {black} Tcl            \
  245.       $tkKeyWords
  246.     }
  247. }
  248.  
  249.  
  250. #===============================================================================
  251. #
  252. # Color iTcl Keywords
  253. #
  254.  
  255. proc Tcl::colorItclKeywords {} {
  256.     global TclmodeVars
  257.  
  258.     set itclKeyWords {
  259.     @scope body class code common component configbody constructor
  260.     define destructor hull import inherit itcl itk itk_component
  261.     itk_initialize itk_interior itk_option iwidgets keep method
  262.     private protected public
  263.     }
  264.  
  265.     if {$TclmodeVars(recogniseItcl)} {
  266.     regModeKeywords -a                 \
  267.      -k $TclmodeVars(commandColor) Tcl         \
  268.      $itclKeyWords
  269.    } else {
  270.     regModeKeywords -a                 \
  271.      -k {black} Tcl                     \
  272.      $itclKeyWords
  273.    }
  274. }
  275.  
  276.  
  277. #===============================================================================
  278. #
  279. # Color Pseudo Tcl Keywords
  280. #
  281.  
  282. proc Tcl::colorPseudoTclKeywords {} {
  283.     global TclmodeVars
  284.     
  285.     set PseudoTclKeywords { 
  286.     lcontains lunion lreverse lremove lunique
  287.     }
  288.     if {$TclmodeVars(recogniseTk)} {
  289.     regModeKeywords -a                 \
  290.      -k $TclmodeVars(commandColor) Tcl         \
  291.      $PseudoTclKeywords
  292.     } else {
  293.     regModeKeywords -a                 \
  294.      -k {black} Tcl                     \
  295.      $PseudoTclKeywords
  296.     }
  297.     
  298. }
  299.  
  300.  
  301. #===============================================================================
  302. #
  303. # Color Tk Commands
  304. #
  305. # add this line if we can handle double 'magic chars'
  306. # -m {tk} 
  307. #
  308.  
  309. proc Tcl::colorTkCommands {} {
  310.     
  311.     global TclmodeVars
  312.  
  313.     set TkCommands {
  314.     tkButtonDown tkButtonEnter tkButtonInvoke tkButtonLeave tkButtonUp
  315.     tkCancelRepeat tkCheckRadioInvoke tkDarken tkEntryAutoScan
  316.     tkEntryBackspace tkEntryButton1 tkEntryClosestGap tkEntryInsert
  317.     tkEntryKeySelect tkEntryMouseSelect tkEntryNextWord tkEntryPaste
  318.     tkEntryPreviousWord tkEntrySeeInsert tkEntrySetCursor
  319.     tkEntryTranspose tkEventMotifBindings tkFDGetFileTypes tkFirstMenu
  320.     tkFocusGroup_BindIn tkFocusGroup_BindOut tkFocusGroup_Create
  321.     tkFocusGroup_Destroy tkFocusGroup_In tkFocusGroup_Out tkFocusOK
  322.     tkListboxAutoScan tkListboxBeginExtend tkListboxBeginSelect
  323.     tkListboxBeginToggle tkListboxCancel tkListboxDataExtend
  324.     tkListboxExtendUpDown tkListboxMotion tkListboxSelectAll
  325.     tkListboxUpDown tkMbButtonUp tkMbEnter tkMbLeave tkMbMotion
  326.     tkMbPost tkMenuButtonDown tkMenuDownArrow tkMenuDup tkMenuEscape
  327.     tkMenuFind tkMenuFindName tkMenuFirstEntry tkMenuInvoke tkMenuLeave
  328.     tkMenuLeftArrow tkMenuMotion tkMenuNextEntry tkMenuNextMenu
  329.     tkMenuRightArrow tkMenuUnpost tkMenuUpArrow tkMessageBox
  330.     tkPostOverPoint tkRecolorTree tkRestoreOldGrab tkSaveGrabInfo
  331.     tkScaleActivate tkScaleButton2Down tkScaleButtonDown
  332.     tkScaleControlPress tkScaleDrag tkScaleEndDrag tkScaleIncrement
  333.     tkScreenChanged tkScrollButton2Down tkScrollButtonDown
  334.     tkScrollButtonUp tkScrollByPages tkScrollByUnits tkScrollDrag
  335.     tkScrollEndDrag tkScrollSelect tkScrollStartDrag tkScrollToPos
  336.     tkScrollTopBottom tkTabToWindow tkTearOffMenu tkTextAutoScan
  337.     tkTextButton1 tkTextClosestGap tkTextInsert tkTextKeyExtend
  338.     tkTextKeySelect tkTextNextPara tkTextNextPos tkTextNextWord
  339.     tkTextPaste tkTextPrevPara tkTextPrevPos tkTextResetAnchor
  340.     tkTextScrollPages tkTextSelectTo tkTextSetCursor tkTextTranspose
  341.     tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu tk_bisque
  342.     tk_chooseColor tk_dialog tk_focusFollowsMouse tk_focusNext
  343.     tk_focusPrev tk_getOpenFile tk_getSaveFile tk_messageBox
  344.     tk_optionMenu tk_popup tk_setPalette tk_textCopy tk_textCut
  345.     tk_textPaste
  346.     }
  347.     
  348.     if {$TclmodeVars(recogniseTk)} {
  349.     regModeKeywords -a             \
  350.      -k $TclmodeVars(commandColor) Tcl     \
  351.      $TkCommands
  352.     } else {
  353.     regModeKeywords -a             \
  354.      -k {black} Tcl             \
  355.      $TkCommands   
  356.  
  357.     }
  358.     unset TkCommands    
  359. }
  360.     
  361. #===============================================================================
  362. #
  363. # Color Symbols
  364.  
  365. proc Tcl::colorSymbols {} {
  366.     
  367.     global TclmodeVars
  368.     
  369.     regModeKeywords -a                 \
  370.       -i "+" -i "-" -i "*" -i "_" -i "\\"    \
  371.       -I $TclmodeVars(symbolColor)              \
  372.       Tcl {}
  373. }
  374.  
  375.  
  376.     
  377. #===============================================================================
  378. #
  379. # Color variables (i.e. words prefaced by '$')
  380.  
  381. proc Tcl::colorMagicStrings {} {
  382.     
  383.     global TclmodeVars
  384.     
  385.     regModeKeywords -a                 \
  386.       -m {$}                    \
  387.       -k $TclmodeVars(magicColor) Tcl {}        
  388. }
  389.  
  390.  
  391. #===============================================================================
  392. #
  393. # Colorize Tcl
  394.  
  395. proc Tcl::colorizeTcl {} {
  396.     global tclCmdColourings tclExtraColourings 
  397.     foreach p $tclCmdColourings {
  398.     $p
  399.     }
  400.     # for some reason, these want to be done last -trf
  401.     foreach p $tclExtraColourings {
  402.     $p
  403.     }
  404.     refresh
  405. }
  406.  
  407. # This is a "dummy" command, necessary for the above proc so that all of
  408. # the "regModeKeywords" commands in the called color procs can be "adds"
  409. # (-a).  When the mode is first invoked, this has to occur before the color
  410. # procs are called.
  411.  
  412. regModeKeywords -k {none} Tcl {}
  413.  
  414. # now we finally colorize
  415.  
  416. Tcl::colorizeTcl
  417.  
  418.     
  419. #===============================================================================
  420. #
  421. # Tcl:: Update Colors -- 
  422. # This allows for changes to take effect without a restart.
  423. # Danger:  Don't include this proc in any {mode}Prefs.tcl file !!!
  424. # This will source the prefs file, and thus put Alpha in an endless loop.
  425. # Instead, use the  Tcl::colorizeTcl  proc in the prefs file, so that
  426. # "Load Prefs File" will update any local variables.     - cbu
  427.  
  428.  
  429. proc Tcl::updateColors {flag} {
  430.     
  431.     global mode PREFS $flag TclmodeVars 
  432.     
  433.     # If the mode has a {mode}Prefs.tcl file, we want to load that as 
  434.     # well, otherwise any keywords contained therein won't be updated
  435.     # without a manual "Load Prefs File".
  436.     
  437.     if {[file exists [file join ${PREFS} ${mode}Prefs.tcl]]} {
  438.     uplevel #0 [list source [file join ${PREFS} ${mode}Prefs.tcl]]
  439.     } 
  440.  
  441.     Tcl::colorizeTcl
  442. }
  443.  
  444. #===============================================================================
  445. #
  446. # Regular Expression Colors --
  447. # Changes color scheme of current window to make it easier to read regular
  448. # expressions.  Preferences aren't actually changed.  "defaultColors" will
  449. # restore to the last stored values of the colors.  -cbu
  450.  
  451. proc Tcl::regularExpressionColors {} {
  452.     
  453.     regModeKeywords -a                 \
  454.       -e {}                    \
  455.       -m {$}                    \
  456.       -s {black}                \
  457.       -k {magenta} Tcl {}            \
  458.       -i "+" -i "-" -i "*" -i "_" -i "\\"    \
  459.       -I {red}  
  460.     
  461.     refresh
  462. }
  463.  
  464. proc Tcl::defaultColors {} {Tcl::colorizeTcl}
  465.     
  466.  
  467. # ◊◊◊◊ end of keyword colorizing ◊◊◊◊ #
  468.  
  469. #===============================================================================
  470.  
  471.  
  472. proc Tcl::MenuProc {menu item} {
  473.     switch -glob $item {
  474.     "reformatProc" {
  475.         procs::reformatEnclosing [getPos]
  476.     }
  477.     "reloadProc" {
  478.         procs::loadEnclosing [getPos]
  479.     }
  480.     "debugProc" {
  481.         set func [procs::pick 1]
  482.         procs::debug $func
  483.     }
  484.     "applyChanges" {
  485.         set w [win::Current]
  486.         if {[regexp -- {\* Debug of (.*) \*( <[0-9]+>)?} $w "" proc]} {
  487.         set f [procs::searchFor $proc]
  488.         if {[string length $f]} {
  489.             if {![catch {procs::replace $f $proc 0}]} {
  490.             bringToFront $w
  491.             killWindow
  492.             }
  493.         } else {
  494.             message "Couldn't find $proc"
  495.         }
  496.         } else {
  497.         message "No debug window is foremost"
  498.         }
  499.     }
  500.     "findProcDefinition" {
  501.         procs::findDefinition
  502.     }
  503.     "quickFindProc" {
  504.         # use the status line
  505.         procs::quickFindDefn
  506.     }
  507.     "switch*" {
  508.         set v "[string tolower [string range $item 8 end]]Sig"
  509.         global $v
  510.         app::launchFore [set $v]
  511.     }
  512.     "addRemoveDollars" {
  513.         togglePrefix \$
  514.     }
  515.     default {
  516.         menu::generalProc Tcl $item 0
  517.     }
  518.     }
  519. }
  520.  
  521. # borrowed from Alphatk
  522. namespace eval alpha {}
  523.  
  524. proc alpha::inAlphaHierarchy {filename} {
  525.     global HOME PREFS tcl_platform
  526.     if {$tcl_platform(platform) == "windows"} {
  527.     set filename [file join [file attributes $filename -longname]]
  528.     } else {
  529.     set filename [file join $filename]
  530.     }
  531.     if {[file pathtype $filename] == "relative"} {
  532.     set filen [file join [pwd] $filename]
  533.     } else {
  534.     set filen $filename
  535.     }
  536.     # Is file in HOME or PREFS?
  537.     if {([string first [file join $HOME] $filen] != 0) \
  538.       && !([file type [file join $HOME]] == "link" \
  539.       && [string first [file readlink [file join $HOME]] $filen] == 0)} {
  540.     if {[info exists PREFS] && [file exists $PREFS]} {
  541.         if {([string first [file join $PREFS] $filen] != 0) \
  542.           && !([file type [file join $PREFS]] == "link" \
  543.           && [string first [file readlink [file join $PREFS]] $filen] == 0)} {
  544.         return 0
  545.         } else {
  546.         return 1
  547.         }
  548.     } else {
  549.         return 0
  550.     }
  551.     } else {
  552.     return 1
  553.     }
  554. }
  555.  
  556. ## 
  557.  # -------------------------------------------------------------------------
  558.  # 
  559.  # "Tcl::rebuildTclIndexForWin" --
  560.  # 
  561.  #  If the file is in Alpha's source tree, use the currently loaded
  562.  #  auto_mkindex.  If it is not, then fire up a separate Tcl application
  563.  #  and use its auto_mkindex (i.e. the standard Tcl one).  It just occured
  564.  #  to me that for Tcl >= 8.0, we could create a new interp, and 
  565.  #  execute auto_mkindex within that to the same effect, but without
  566.  #  the overhead of a whole new process (especially a Tk one!).
  567.  # -------------------------------------------------------------------------
  568.  ##
  569. proc Tcl::rebuildTclIndexForWin {} {
  570.     if {[alpha::inAlphaHierarchy [win::Current]]} {
  571.     auto_mkindex [file dirname [win::Current]]
  572.     auto_reset
  573.     } else {
  574.     # This will currently launch a Tk shell, which isn't ideal.
  575.     set dir [file dirname [win::Current]]
  576.     tcltk::launchNewShell "auto_mkindex $dir" "exit"
  577.     }
  578. }
  579.  
  580. proc tcltk::menuProc {menu item} {
  581.     global tcl_platform tclshSig
  582.     switch -- $item {
  583.     "evaluateRemotely" {
  584.         global evaluateRemotely
  585.         set evaluateRemotely [expr {1 - $evaluateRemotely}]
  586.     }
  587.     "executeFileInRemoteShell" {
  588.         tcltk::executeInRemoteShell [win::Current]
  589.     }
  590.     "addWindowToListOfExecutables" {
  591.         global tcltk::executables
  592.         lappend tcltk::executables [win::Current]
  593.         prefs::modified tcltk::executables
  594.         menu::buildSome tclMenu
  595.     }
  596.     "executeCommand" {
  597.         set cmd [getline "Please enter the script to send to tcl-tk"]
  598.         if {$cmd == ""} {return}
  599.         if {$tcl_platform(platform) == "macintosh"} {
  600.         set res [AEBuild -r -t 30000 '$tclshSig' misc dosc ---- "“$cmd”"]
  601.         } else {
  602.         set res [tcltk::evaluate $cmd]
  603.         }
  604.         alertnote "Result was '$res'"
  605.     }
  606.     default {
  607.         global tcltk::executables
  608.         foreach ex ${tcltk::executables} {
  609.         if {[file tail $ex] == $item} {
  610.             tcltk::executeInRemoteShell $ex
  611.             break
  612.         }
  613.         }
  614.     }
  615.     }
  616. }
  617.  
  618. proc tcltk::executeInRemoteShell {f} {
  619.     global evaluateRemotely
  620.     set realName [win::StripCount $f]
  621.     tcltk::launchNewShell \
  622.       "cd [file dirname $realName]" \
  623.       "source [file tail $realName]"
  624.     if {!$evaluateRemotely} {
  625.     set evaluateRemotely 1
  626.     }
  627. }
  628.  
  629. if {[info tclversion] < 8.0} {
  630.     proc tcltk::evaluateRemoteSynchronise {args} {
  631.     global evaluateRemotely tclMenu
  632.     catch {markMenuItem "tcl-tk" evaluateRemotely $evaluateRemotely}
  633.     if {$evaluateRemotely} {
  634.         if {[info commands notRemoteEvaluate] == ""} {
  635.         rename evaluate notRemoteEvaluate
  636.         ;proc evaluate {} {remoteEvaluate}
  637.         }
  638.         menu::replaceRebuild tclMenu "•320"
  639.     } else {
  640.         if {[info commands notRemoteEvaluate] != ""} {
  641.         rename evaluate {}
  642.         rename notRemoteEvaluate evaluate
  643.         }
  644.         menu::replaceRebuild tclMenu "•269"
  645.     }
  646.     }
  647. } else {
  648.     proc tcltk::evaluateRemoteSynchronise {args} {
  649.     global evaluateRemotely tclMenu
  650.     catch {markMenuItem "tcl-tk" evaluateRemotely $evaluateRemotely}
  651.     if {$evaluateRemotely} {
  652.         if {[info commands ::notRemoteEvaluate] == ""} {
  653.         rename ::evaluate ::notRemoteEvaluate
  654.         ;proc ::evaluate {} {remoteEvaluate}
  655.         }
  656.         menu::replaceRebuild tclMenu "•320"
  657.     } else {
  658.         if {[info commands ::notRemoteEvaluate] != ""} {
  659.         rename ::evaluate {}
  660.         rename ::notRemoteEvaluate ::evaluate
  661.         }
  662.         menu::replaceRebuild tclMenu "•269"
  663.     }
  664.     }
  665. }
  666.  
  667.  
  668. proc remoteEvaluate {} {
  669.     message "Remote reply: [tcltk::evaluate [getSelect]]"
  670. }
  671.  
  672. proc tcltk::quitRemote {} {
  673.     global tclshSig tcl_platform
  674.     if {$tcl_platform(platform) == "macintosh"} {
  675.     app::ensureRunning $tclshSig
  676.     if {[catch {set r [tclAE::build::resultData -t 30000 '${tclshSig}' \
  677.         misc dosc \
  678.         ---- [tclAE::build::TEXT exit] \
  679.         ]} res]} {
  680.         set res "Error: $res"
  681.     }            
  682.     } else {
  683.     global tclshInterp
  684.     if {![info exists tclshInterp]} {
  685.         if {[catch {tcltk::findTclshInterp}]} {
  686.         return "No shell selected"
  687.         }
  688.     }
  689.     if {$tcl_platform(platform) == "windows"} {
  690.         if {[dde services TclEval $tclshInterp] == ""} {
  691.         alertnote "The remote shell has died, please select a new one."
  692.         unset tclshInterp
  693.         return [tcltk::quitRemote exit]
  694.         }
  695.         catch {dde execute TclEval $tclshInterp "exit"}
  696.     } else {
  697.         catch {send $tclshInterp exit}
  698.     }
  699.     }
  700. }
  701.  
  702. proc tcltk::evaluate {what} {
  703.     global tclshSig tcl_platform
  704.     if {$tcl_platform(platform) == "macintosh"} {
  705.     app::ensureRunning $tclshSig
  706.     if {[catch {set r [tclAE::build::resultData -t 30000 '${tclshSig}' \
  707.                 misc dosc \
  708.               ---- [tclAE::build::TEXT $what] \
  709.             ]} res]} {
  710.         set res "Error: $res"
  711.     }            
  712.     #catch {dosc -c '${tclshSig}' -s $what} res
  713.     #return $res
  714.     } else {
  715.     global tclshInterp
  716.     if {![info exists tclshInterp]} {
  717.         if {[catch {tcltk::findTclshInterp}]} {
  718.         return "No shell selected"
  719.         }
  720.     }
  721.     if {$tcl_platform(platform) == "windows"} {
  722.         if {[dde services TclEval $tclshInterp] == ""} {
  723.         alertnote "The remote shell has died, please select a new one."
  724.         unset tclshInterp
  725.         return [tcltk::evaluate $what]
  726.         }
  727.         dde execute TclEval $tclshInterp [list catch $what alpha_result]
  728.         return [dde request TclEval $tclshInterp alpha_result]
  729.     } else {
  730.         catch {send $tclshInterp $what} res
  731.     }
  732.     }
  733.     return $res
  734. }
  735.  
  736. proc tcltk::listInterps {} {
  737.     global tcl_platform
  738.     if {$tcl_platform(platform) == "windows"} {
  739.     set res {}
  740.     foreach service [dde services TclEval ""] {
  741.         lappend res [lindex $service 1]
  742.     }
  743.     return $res
  744.     } else {
  745.     return [winfo interps]
  746.     }
  747. }
  748.  
  749. proc tcltk::findTclshInterp {} {
  750.     global tclshInterp tclshSigs tclshSig
  751.     set old [tcltk::listInterps]
  752.     set shel [listpick -p "Use which Tcl shell?" [concat $old \
  753.       [list "------------------" "Launch new shell"]]]
  754.     if {$shel == "Launch new shell"} {
  755.     tcltk::launchNewShell
  756.     } else {
  757.     set tclshInterp $shel
  758.     }
  759. }
  760.  
  761. ## 
  762.  # -------------------------------------------------------------------------
  763.  # 
  764.  # "tcltk::launchNewShell" --
  765.  # 
  766.  #  Startup up a new Tcl shell, ensuring that we can communicate with that
  767.  #  shell.  On Unix/MacOS this should be easy using 'send' or apple-events
  768.  #  respectively.  On Windows we have to set up the new shell as a dde
  769.  #  server.  We do this with the script 'winRemoteShell.tcl'.
  770.  #  
  771.  #  Any extra 'args' passed to this procedure are executed, one by one,
  772.  #  in the new shell.
  773.  # -------------------------------------------------------------------------
  774.  ##
  775. proc tcltk::launchNewShell {args} {
  776.     global tclshInterp tclshSigs tclshSig tcl_platform HOME
  777.     set old [tcltk::listInterps]
  778.     if {$tcl_platform(platform) == "windows"} {
  779.     app::runScript tclsh "Tcl shell" [file join $HOME Tools winRemoteShell.tcl] 2
  780.     } else {
  781.     app::launchElseTryThese $tclshSigs tclshSig "Please locate the remote Tcl application"
  782.     }
  783.     while {[tcltk::listInterps] == $old} {
  784.     update
  785.     }
  786.     set tclshInterp [lremove -l [tcltk::listInterps] $old]
  787.     # We're left with two items
  788.     set tclshInterp [lindex $tclshInterp 0]
  789.     
  790.     if {[llength $args]} {
  791.     foreach arg $args {
  792.         set res [tcltk::evaluate $arg]
  793.     }
  794.     return $res
  795.     }
  796.     return ""
  797. }
  798.  
  799. # ◊◊◊◊ Quick Find Proc… ◊◊◊◊ #
  800.  
  801. proc procs::quickFindDefn {} {
  802.     Tcl::DblClickHelper [prompt::statusLineComplete "proc" procs::complete]
  803. }
  804.  
  805. if {[info tclversion] < 8.0} {
  806.     proc procs::complete {pref} {
  807.     return [info commands ${pref}*]
  808.     }
  809. } else {
  810.     proc procs::complete {pref} {
  811.     if {[regexp {(.*)([^:]+)$} $pref "" start tail]} {
  812.         set cmds [info commands ${pref}*]
  813.         foreach child [namespace children ::$start] {
  814.         if {[string match "::${tail}*" $child]} {
  815.             foreach cmd [info commands ${start}${child}::*] {
  816.             lappend cmds [string trimleft $cmd :]
  817.             }
  818.         }
  819.         }
  820.         return $cmds
  821.     } else {
  822.         return [info commands ${pref}*]
  823.     }
  824.     }
  825. }
  826.  
  827. # ◊◊◊◊ electric behaviour ◊◊◊◊ #
  828. proc Tcl::electricLeft {} {
  829.     if {[literalChar]} { insertText "\{"; return }
  830.     set pat "\}\[ \t\r\n\]*(else(if)?)\[ \t\r\n\]*\$"
  831.     set p [getPos]
  832.     if { [set res [findPatJustBefore "\}" "$pat" $p word]] == "" } { 
  833.     insertText "\{"
  834.     return
  835.     }
  836.     # we have an if/else(if)/else
  837.     global structuralElectricElseBrace
  838.     # The behaviour here is optional, because some people may not
  839.     # like this more structured entry.
  840.     if {$structuralElectricElseBrace} {
  841.     switch -- $word {
  842.         "else" {
  843.         deleteText [lindex $res 0] $p
  844.         elec::Insertion "\} $word \{\r\t••\r\}\r••"
  845.         }
  846.         "elseif" {
  847.         deleteText [lindex $res 0] $p
  848.         elec::Insertion "\} $word \{••\} \{\r\t••\r\}\r••"
  849.         }
  850.     }
  851.     } else {
  852.     switch -- $word {
  853.         "else" {
  854.         replaceText [lindex $res 0] $p "\} $word \{\r"
  855.         bind::IndentLine
  856.         }
  857.         "elseif" {
  858.         replaceText [lindex $res 0] $p "\} $word \{"
  859.         }
  860.     }
  861.     }
  862. }
  863.  
  864. proc Tcl::electricRight {} {
  865.     if {[literalChar]} { insertText "\}"; return }
  866.     set p [getPos]
  867.     if { [regexp "\[^ \t\]" [getText [lineStart $p] $p]] } {
  868.     insertText "\}"
  869.     blink [matchIt "\}" [pos::math $p - 1]]
  870.     return
  871.     }
  872.     set start [lineStart $p]
  873.     insertText "\}"
  874.     createTMark tcl_er [getPos]
  875.     backwardChar
  876.     bind::IndentLine
  877.     gotoTMark tcl_er ; removeTMark tcl_er
  878.     bind::CarriageReturn
  879.     blink [matchIt "\}" [pos::math $start - 1]]
  880. }
  881.  
  882. ## 
  883.  # -------------------------------------------------------------------------
  884.  # 
  885.  # "Tcl::correctIndentation" --
  886.  # 
  887.  #  Returns the correct indentation for the line containing $pos, if that
  888.  #  line were to contain ordinary characters only.  It is the 
  889.  #  responsibility of the calling procedure to ensure that if we are to
  890.  #  insert/have a line already, that that information is taken into
  891.  #  account, by passing in the argument 'next'
  892.  # -------------------------------------------------------------------------
  893.  ##
  894. proc Tcl::correctIndentation {pos {next ""}} {
  895.     global indent_amounts indentSlashEndLines
  896.     # preliminaries
  897.     if {[pos::compare [set beg [lineStart $pos]] == [minPos]]} { return 0 }
  898.     # if the current line is a comment, we have to check some
  899.     # special cases
  900.     if {[string index $next 0] == "\#"} {
  901.     set p [prevLineStart $beg]
  902.     if {[catch {set p [search -s -f 0 -r 1 -i 0 -m 0 "^\[ \t\]*\[^ \t\r\n\]" \
  903.       [pos::math $beg - 1]]}]} {
  904.         # check for search bug at beginning of file.
  905.         if {[pos::compare $p == [minPos]]} {
  906.         if {[getText [minPos] [pos::math [minPos] + 2]] == "\#\#"} {
  907.             if {([string range $next 0 1] != "\#\#")} {
  908.             return 1
  909.             } else {
  910.             return 0
  911.             }
  912.         }
  913.         }
  914.         return 0
  915.     }
  916.     set prev [pos::math [lindex $p 1] - 1]
  917.     set p [lindex $p 0]
  918.     if {[lookAt $prev] != "\#" || ($beg == [minPos])} {
  919.         # not a comment, so indent with code
  920.     } else {
  921.         set lwhite [posX $prev]
  922.         # it's a comment
  923.         if {[getText $prev [pos::math $prev + 2]] == "\#\#" && \
  924.           [lookAt [pos::math $prev + 2]] != "\#" \
  925.           && ([string range $next 0 1] != "\#\#")} {
  926.         # it's a comment paragraph
  927.         incr lwhite 
  928.         }
  929.     }
  930.     }
  931.     set next [string index $next 0]
  932.     if {![info exists lwhite]} {
  933.     if {![catch {search -s -f 0 -r 1 -i 0 -m 0 "^\[ \t\]*\[^\# \t\r\n\]" [pos::math $beg - 1]} lst]} {
  934.         # Find the last non-comment line and get its leading whitespace    
  935.         set lwhite [posX [pos::math [lindex $lst 1] - 1]]
  936.         set pe1 [lookAt [pos::math $beg - 2]]
  937.         set lst [lindex $lst 0]
  938.         set lastC [lookAt [lindex [search -s -f 0 -r 1 -i 0 -m 0 "\[^ \t\r\n\]" [pos::math [nextLineStart $lst] - 1]] 0]]
  939.         if {$next == "\}"} {
  940.         incr lwhite $indent_amounts(-2)
  941.         set pe2 [lookAt [pos::math [prevLineStart $beg] - 2]]
  942.         if {$pe1 == "\\"} {
  943.             incr lwhite $indent_amounts(1)
  944.         } else {
  945.             if {$pe2 == "\\"} {
  946.             incr lwhite $indent_amounts(-1)
  947.             }
  948.         }
  949.         if {$lastC == "\{"} {incr lwhite $indent_amounts(2)}    
  950.         } else { 
  951.         if {$pe1 == "\\"} {
  952.             if {[lookAt [pos::math [prevLineStart $beg] - 2]] != "\\"} {
  953.             incr lwhite $indent_amounts($indentSlashEndLines)
  954.             }
  955.         } else {
  956.             if {$lastC == "\{"} {incr lwhite $indent_amounts(2)}    
  957.             if {[lookAt [pos::math $lst - 2]] == "\\"} {
  958.             incr lwhite $indent_amounts(-$indentSlashEndLines)
  959.             }
  960.         }
  961.         }
  962.     } else {
  963.         # basically failed in all the above, so keep current indentation
  964.         set lwhite [posX [text::firstNonWsLinePos $beg]]
  965.     }
  966.     }
  967.     return [expr {$lwhite > 0 ? $lwhite : 0}]
  968. }
  969.  
  970. ## 
  971.  # -------------------------------------------------------------------------
  972.  #   
  973.  # "Tcl::indentLine" --
  974.  #  
  975.  #  Indentation for Tcl mode.  Better and faster than the generic procedure
  976.  # -------------------------------------------------------------------------
  977.  ##
  978. proc Tcl::indentLine {} {
  979.     set beg [lineStart [set p [getPos]]]
  980.     set text [getText $beg [nextLineStart $beg]]
  981.     regexp "^\[ \t\]*" $text white
  982.     set next [pos::math $beg + [string length $white]]
  983.     set nextp [pos::math $next + 2]
  984.     if {[pos::compare $nextp > [maxPos]]} {
  985.     set nextp [maxPos]
  986.     }
  987.     set lwhite [Tcl::correctIndentation [getPos] [getText $next $nextp]]
  988.     
  989.     set lwhite [text::indentOf $lwhite]
  990.     if {$white != $lwhite} {
  991.     replaceText $beg $next $lwhite
  992.     }
  993.     goto [pos::math $beg + [string length $lwhite]]
  994.     # To keep relative position.
  995.     #goto [pos::math $p + [string length $lwhite] - [pos::diff $beg $next]]
  996. }
  997.  
  998. # ◊◊◊◊ Tcl Menu support ◊◊◊◊ #
  999.  
  1000. proc procs::reformatEnclosing {pos} {
  1001.     set p [procs::findEnclosing $pos "proc|((itcl::)?(body|configbody))" 0 1]
  1002.     eval select $p
  1003.     ::indentRegion
  1004. }
  1005.  
  1006. proc procs::loadEnclosing {pos} {
  1007.     if {[catch {procs::findEnclosing $pos "proc|((itcl::)?(body|configbody))" 0 1} p]} {
  1008.     evaluateLine $pos
  1009.     } else {
  1010.     eval select $p
  1011.     if {[catch {uplevel \#0 evaluate} err]} {
  1012.         if {[regexp {can't create procedure "(.*)": unknown namespace} $err "" pr]} {
  1013.         if {[dialog::yesno "The procedure '$pr' couldn't be loaded, because\
  1014.           it is in an unknown namespace.  Shall I create the namespace and\
  1015.           try again?"]} {
  1016.             ensureNamespaceExists $pr
  1017.             return [procs::loadEnclosing $pos]
  1018.         }
  1019.         }
  1020.     }
  1021.     }
  1022.     goto $pos
  1023. }
  1024.  
  1025. proc procs::findDefinition {} {
  1026.     set func [procs::pick 1]
  1027.     editMark [procs::find $func] $func
  1028. }
  1029.  
  1030. ## 
  1031.  # -------------------------------------------------------------------------
  1032.  # 
  1033.  # "insertDivider" --
  1034.  # 
  1035.  #  Modified from Vince's original to allow you to just select part of
  1036.  #  an already written comment and turn it into a Divider. -trf
  1037.  # -------------------------------------------------------------------------
  1038.  ##
  1039. proc insertDivider {} {
  1040.     if {[isSelection]} {
  1041.     set enfoldThis [getSelect]
  1042.     beginningOfLine
  1043.     killLine
  1044.     insertText "# ◊◊◊◊ $enfoldThis ◊◊◊◊ #"
  1045.     return
  1046.     } 
  1047.     elec::Insertion "# ◊◊◊◊ •• ◊◊◊◊ #"
  1048. }
  1049.  
  1050. # ◊◊◊◊ Info providers ◊◊◊◊ #
  1051.  
  1052. proc Tcl::DblClick {from to shift option control} {
  1053.     
  1054.     # if cmd and cntrl were pressed, we look to select part of
  1055.     # a combination word (less any leading dollar sign) -trf
  1056.     if {$control != 0} {
  1057.     set clickedPos [getPos]    
  1058.     if {[lookAt $from] == "\$"} {
  1059.         set from [pos::math $from + 1]
  1060.     } 
  1061.     set sel_start $clickedPos 
  1062.     set selStartNotDetermined 1
  1063.     while {$selStartNotDetermined && ([pos::math $sel_start > $from])} {
  1064.         set char [lookAt $sel_start] 
  1065.         if {[regexp {_} $char]} {
  1066.         set sel_start [pos::math $sel_start + 1]
  1067.         set selStartNotDetermined 0
  1068.         } elseif {[regexp {[A-Z]} $char]} {
  1069.         set selStartNotDetermined 0
  1070.         } else {
  1071.         set sel_start [pos::math $sel_start -1]
  1072.         } 
  1073.     }
  1074.     set sel_end   $clickedPos 
  1075.     set selEndNotDetermined 1
  1076.     while {$selEndNotDetermined && ([pos::math $sel_end <= $to])} {
  1077.         set char [lookAt $sel_end] 
  1078.         if {[regexp "\[A-Z_ \t\r\]" $char]} {
  1079.         set selEndNotDetermined 0
  1080.         } else {
  1081.         set sel_end [pos::math $sel_end + 1]
  1082.         } 
  1083.     }
  1084.     select $sel_start $sel_end 
  1085.     return
  1086.     } 
  1087.     
  1088.     # otherwise, we try to impart some extra info
  1089.     select $from $to
  1090.     
  1091.     # if this was called using the shortcut key, the selection 
  1092.     # may include more than just the proc name, so we dust off
  1093.     # the selection first.
  1094.     set procName [getSelect] 
  1095.     set procName [string trimright $procName "'"]
  1096.     regexp -- "^proc\[ \t\]+(\[^ \t\]+)" $procName all procName 
  1097.     set procName [string trim $procName]
  1098.  
  1099.     # This might have been called from within a Trace window, 
  1100.     # in which case we want to move this window to the right
  1101.     # and push its mark.
  1102.     if {[regexp "^\\* (Tcl error|Trace|Stack)" [win::CurrentTail]]} {
  1103.     lappend selectionEndPoints [getPos] [selEnd]
  1104.     shrinkRight
  1105.     placeBookmark
  1106.     set got [search -s -n -f 1 -r 1 -m 0 -- \
  1107.       "\\(procedure \"[quote::Regfind $procName]\" line \[0-9\]+\\)" \
  1108.       [pos::math [getPos] -12]]
  1109.     if {[llength $got]} {
  1110.         eval select $got
  1111.         regexp "(\[0-9\]+)\\)\$" [getSelect] "" line
  1112.         if {![catch [list procs::debug $procName $line]]} {
  1113.         return
  1114.         }
  1115.     }
  1116.     set markSet 1
  1117.     } else {
  1118.     set markSet 0
  1119.     } 
  1120.     
  1121.     if {[catch [list Tcl::DblClickHelper $procName]]} {
  1122.     message "No docs $shift $control $option"
  1123.     } else {
  1124.     bringToFront [win::CurrentTail]
  1125.     }
  1126.     
  1127.     if {$markSet} {
  1128.     returnToBookmark
  1129.     eval select $selectionEndPoints 
  1130.     }
  1131. }
  1132.  
  1133.  
  1134. # Now finds commands in Alpha Commands,
  1135. # which has a <cr> immediately after them, e.g. beep, ticks.
  1136. proc Tcl::DblClickHelper {text} {
  1137.     global HOME auto_index auto_path TclmodeVars
  1138.     # Is it a loadable proc?
  1139.     if {[string length [set f [procs::find $text]]]} {
  1140.     if {[editMark $f $text]} {
  1141.         # some marking schemes commonly used for Tcl modes
  1142.         goto [lindex [search -s -f 1 -r 1 -m 0 -- "proc\[ \t\]+${text}\[ \t\]" [minPos]] 0]
  1143.     }
  1144.     return
  1145.     }
  1146.     
  1147.     if {[info exists "auto_index($text)"]} {
  1148.     if {[editMark "$auto_index($text)" $text]} {
  1149.         # some marking schemes commonly used for Tcl modes
  1150.         goto [lindex [search -s -f 1 -r 1 -m 0 -- "proc\[ \t\]+${text}\[ \t\]" [minPos]] 0]
  1151.     }
  1152.     return
  1153.     }
  1154.     # Is it a built-in Alpha command?
  1155.     set lines [grep "^• $text\( |\$)" [file join $HOME Help "Alpha Commands"]]
  1156.     if {[string length $lines]} {
  1157.     help::openFile "Alpha Commands"
  1158.     if {[catch {editMark [file join $HOME Help "Alpha Commands"] $text}]} {
  1159.         # mark failed for some reason, but we have the line number
  1160.         # anyway.
  1161.         goto [rowColToPos [string trimright [lindex [lindex [split $lines "\n"] 1] 3] :] 0]
  1162.     }
  1163.     setWinInfo read-only 1
  1164.     return
  1165.     }
  1166.     # Is it a core Tcl command?
  1167.     if {[info tclversion] >= 8.0} {
  1168.     interp create sub
  1169.     set res [sub eval "info commands $text"]
  1170.     interp delete sub
  1171.     if {[string length $res]} {
  1172.         url::execute "$TclmodeVars(tclHelpLocation)${text}.htm"
  1173.         return
  1174.     }
  1175.     }
  1176.     
  1177.     set lines [grep "^     $text -" [file join $HOME Help "Tcl Commands"]]
  1178.     if {[string length $lines]} {
  1179.     help::openFile "Tcl Commands"
  1180.     if {[catch {editMark [file join $HOME Help "Tcl Commands"] $text}]} {
  1181.         # mark failed for some reason, but we have the line number
  1182.         # anyway.
  1183.         goto [rowColToPos [string trimright [lindex [lindex [split $lines "\n"] 1] 3] :] 0]
  1184.     }
  1185.     setWinInfo read-only 1
  1186.     return
  1187.     }
  1188.     # Is it a global variable?
  1189.     if {[llength [info globals [string trimleft $text {$}]]]==1} {
  1190.     showVarValue [string trimleft $text {$}]
  1191.     return
  1192.     }
  1193.     # (becoming desperate) is it a mark in the current file?
  1194.     if {[lsearch [getNamedMarks -n] ${text}] != -1} {
  1195.     gotoMark $text
  1196.     return
  1197.     }
  1198.     error ""
  1199. }
  1200.  
  1201. #############################################################################
  1202. #  Report the current value of a global variable, chosen interactively
  1203. #  from a list of all active variables.
  1204. #
  1205. #  If the variable is an array, or its value is too big to fit in an 
  1206. #  alertnote, then its contents are listed in a new window, otherwise 
  1207. #  the variable's value is displayed in an alertnote.
  1208. #
  1209. proc getVarValue {} {
  1210.     if {[catch {getText [getPos] [selEnd]} def]} {set def ""}
  1211.     set var [getVarFromList $def]
  1212.     if {[string length $var] == 0} return
  1213.     showVarValue $var
  1214. }
  1215.  
  1216. if {[info tclversion] < 8.0} {
  1217.     
  1218.     proc getVarFromList {{def ""}} {
  1219.     return [listpick -p {Which var?} -L $def [lsort -ignore [info globals]]]
  1220.     }
  1221.     
  1222. } else {
  1223.     
  1224.     proc getVarFromList {{def ""}} {
  1225.     set ns "[namespace qualifiers $def]"
  1226.     set def [namespace tail $def]
  1227.     
  1228.     set items {}
  1229.     foreach var [info vars "${ns}::*"] {
  1230.         lappend items [namespace tail $var]
  1231.     }
  1232.     foreach space [namespace children $ns] {
  1233.         lappend items "[namespace tail $space]::"
  1234.     }
  1235.     
  1236.     set items [concat "::" [lsort -ignore $items]]
  1237.     set var [listpick -p "Which var in namespace ${ns}::?" -L $def $items]
  1238.     if {$var == "::"} {
  1239.         set var [getVarFromList $ns]
  1240.     } elseif {[namespace qualifiers $var] != ""} {
  1241.         set var [getVarFromList "${ns}::${var}"]
  1242.     } else {
  1243.         set var "${ns}::${var}"
  1244.     }
  1245.     return $var
  1246.     }
  1247. }
  1248.  
  1249. #############################################################################
  1250. #  Report the current value of a global variable, chosen interactively
  1251. #  from a list of all active variables.
  1252. #
  1253. #  If the variable is an array, or its value is too big to fit in an 
  1254. #  alertnote, then its contents are listed in a new window, otherwise 
  1255. #  the variable's value is displayed in an alertnote.
  1256. #
  1257. proc showVarValue {var} {
  1258.     global $var
  1259.     if {![array exists $var]} {
  1260.         viewValue $var [set $var]
  1261.     } else {
  1262.     new -n "* $var *" -info [listArray $var]
  1263.     # if 'shrinkWindow' is loaded, call it to trim the output window.
  1264.     catch {shrinkWindow 2}
  1265.     }
  1266.  
  1267. #############################################################################
  1268. #  List the name and value of each element of the array $arrName.
  1269. #  (Convenient to use as a shell command.)
  1270. #
  1271. proc listArray {arrName} {
  1272.     global $arrName
  1273.     if {[array exists $arrName]} {
  1274.     set lines {}
  1275.         foreach nm [array names $arrName] {
  1276.             lappend lines "\"$nm\"\t\{[set ${arrName}($nm)]\}"
  1277.         }
  1278.         return [join $lines \r]
  1279.     } else {
  1280.         alertnote "\"$arrName\" doesn't exist in this context"
  1281.     }
  1282. }
  1283.  
  1284.  
  1285. proc 1xTop2xShowComment {} {
  1286.     global __1x2xShowPos
  1287.     
  1288.     ensureset __1x2xShowPos [minPos]
  1289.     set pos [getPos]
  1290.     # if we have a proc definition selected
  1291.     if {[regexp -- proc [getSelect]]} {
  1292.     set startCommentPos [procs::getCommentPos $pos]
  1293.     if {[pos::compare $__1x2xShowPos == $pos]} {
  1294.         # and, we already put it at the top
  1295.         if {[pos::compare $pos == $startCommentPos]} {
  1296.         message "           No comment for proc"
  1297.         } else {
  1298.         display $startCommentPos 
  1299.         }
  1300.         
  1301.         
  1302.     } else {
  1303.         # else, this is the first time the proc def is to be 
  1304.         # to be moved
  1305.         insertToTop
  1306.         set __1x2xShowPos [getPos]
  1307.         # just check and let user know if a comment is above
  1308.         # this proc.
  1309.         if {[pos::compare [getPos] == $startCommentPos]} {
  1310.         message "           No comment for proc"
  1311.         } else {
  1312.         message "Comments are above, press again to see them"
  1313.         }
  1314.     }
  1315.     
  1316.     } else {
  1317.     # user wants a normal line moved to the top
  1318.     insertToTop
  1319.     set __1x2xShowPos [minPos]
  1320.     }
  1321. }
  1322.  
  1323. Bind Clear 1xTop2xShowComment Tcl
  1324.  
  1325. # ◊◊◊◊ Marking ◊◊◊◊ #
  1326.  
  1327. ## 
  1328.  # -------------------------------------------------------------------------
  1329.  #     
  1330.  # "Tcl::parseFuncs" --
  1331.  #    
  1332.  # This proc is called by the "braces"    pop-up.    It returns a dynamically
  1333.  # created, alphabetical, list of "pseudo-marks".
  1334.  #    
  1335.  #    Author:    Tom Fetherston
  1336.  # -------------------------------------------------------------------------
  1337.  ## called by the "{}" button
  1338. proc Tcl::parseFuncs {} {
  1339.     global TclmodeVars
  1340.     set end [maxPos]
  1341.     set pos [minPos]
  1342.     set l {}
  1343.     set markExpr "^\[ \t\]*(itcl(::|_))?(class|body|proc|method|(config)?body)\[ \t\]"
  1344.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 "$markExpr" $pos} res]} {
  1345.     set start [lindex $res 0]
  1346.     set end [nextLineStart $start]
  1347.     set t [getText $start $end]
  1348.     append t "\}"
  1349.     set argLabel {}
  1350.     regsub "^itcl(::|_)" [lindex $t 0] "" what
  1351.     switch -- [lindex $t 0] {
  1352.         "proc" {
  1353.         append argLabel [set word [lindex $t 1]]
  1354.         #get the list of arguments
  1355.         set argsList [lindex $t 2]
  1356.         if {[llength $argsList] > 0} {
  1357.             append argLabel " \{"
  1358.             foreach arg $argsList {
  1359.             if {[llength $arg] == 2 } {
  1360.                 append argLabel "¿"
  1361.             } elseif {[set arg] != "args"} {
  1362.                 append argLabel "•"
  1363.             } else {
  1364.                 append argLabel "…"
  1365.             }
  1366.             }
  1367.             append argLabel "\}"                    
  1368.         } 
  1369.         }
  1370.         default {
  1371.         append argLabel [set word [lindex $t 1]]
  1372.         }
  1373.     }
  1374.     if {[info exists cnts($word)]} {
  1375.         # This section handles duplicate. i.e., overloaded names
  1376.         incr cnts($word)
  1377.     } else {
  1378.         set cnts($word) 1
  1379.     }
  1380.     # if this is the only occurence of this proc, remember where it starts
  1381.     lappend indx($word) [lineStart [pos::math $start - 1]]
  1382.     # associate name and tag
  1383.     set tag($word) $argLabel
  1384.     
  1385.     # advance pos to where we want to start the next search from
  1386.     set pos $end
  1387.     }
  1388.     
  1389.     set rtnRes {}
  1390.     
  1391.     if {[info exists indx]} {
  1392.     foreach hn [lsort -ignore [array names indx]] {
  1393.         set num [llength $indx($hn)]
  1394.         if {$num > 1} {
  1395.         for {set i 0} {$i < $num} {} {
  1396.             set next [nextLineStart [lindex $indx($hn) $i]]
  1397.             incr i
  1398.             lappend rtnRes "$tag($hn) \($i of $num\)" $next
  1399.         }
  1400.         } else {
  1401.         set next [nextLineStart [lindex $indx($hn) 0]]
  1402.         lappend rtnRes $tag($hn) $next
  1403.         }
  1404.     }
  1405.     }
  1406.     return $rtnRes 
  1407. }
  1408.  
  1409. # called by the "M" button
  1410. proc Tcl::MarkFile {} {
  1411.     global structuralMarks
  1412.     set end [maxPos]
  1413.     set pos [minPos]
  1414.     set l {}
  1415.     if {$structuralMarks} {
  1416.     set markExpr {^[;     ]*(itcl(::|_))?(class|namespace eval|proc|method|(config)?body|# ◊◊◊◊)[     ]}
  1417.     } else {
  1418.     set markExpr {^[;     ]*(itcl(::|_))?(class|namespace eval|proc|method|(config)?body)[     ]}
  1419.     }
  1420.     set class ""
  1421.     set hasMarkers 0
  1422.     set already [list]
  1423.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 "$markExpr" $pos} res]} {
  1424.     set start [lindex $res 0]
  1425.     set end [nextLineStart $start]
  1426.     set t [string trim [getText $start $end] ";"]
  1427.     append t "\}"
  1428.     if {[catch {lindex $t 0}]} {
  1429.         # wasn't a well formed list
  1430.         set pos $end
  1431.         continue
  1432.     }
  1433.     regsub "^itcl(::|_)" [lindex $t 0] "" what
  1434.     switch -glob [string trim $what ";"] {
  1435.         "proc" -
  1436.         "configbody" { set text [lindex $t 1] }
  1437.         "method" { set text ${class}::[lindex $t 1] }
  1438.         "body" { 
  1439.         regexp {[a-zA-Z_][a-zA-Z_/0-9]*::[a-zA-Z_][a-zA-Z_/0-9]* } \
  1440.           "[lindex $t 1] " text
  1441.         }
  1442.         "namespace" {
  1443.         set ns [lindex $t 2]
  1444.         if {[regexp {[^a-zA-Z0-9]} $ns]} {
  1445.             set pos $end
  1446.             continue
  1447.         }
  1448.         set text "${ns} 111" 
  1449.         }
  1450.         "*class" { 
  1451.         set class [lindex $t 1]
  1452.         set text "${class} 000" 
  1453.         }
  1454.         "#" { 
  1455.         regexp "# ◊◊◊◊ (.*) ◊◊◊◊" $t all text
  1456.         if {[regexp "^(    )|(    )# ◊◊◊◊ " $t]} {
  1457.             set text " •$text"
  1458.         } else {
  1459.             set text "•$text"
  1460.         }                
  1461.         set hasMarkers 1
  1462.         }
  1463.     }
  1464.     set pos $end
  1465.     while { [lsearch -exact $already $text] != -1 } {
  1466.         set text "$text "
  1467.     }
  1468.     lappend already $text
  1469.  
  1470.     if {$structuralMarks} {
  1471.         lappend asEncountered $text
  1472.         set arr inds
  1473.     } else {
  1474.         if {[string index $t 0] == ";"} {
  1475.         set arr iinds
  1476.         } else {
  1477.         set arr inds
  1478.         }
  1479.     }
  1480.     set ${arr}($text) [lineStart [pos::math $start - 1]]
  1481.     }
  1482.     
  1483.     set class "#"
  1484.     foreach arr {inds iinds} {
  1485.     if {[info exists $arr]} {
  1486.         if {$arr == "iinds"} {
  1487.         # What is the goal of this line?
  1488.         setNamedMark "-" [minPos] [minPos] [minPos]
  1489.         }
  1490.         if {$structuralMarks} {
  1491.         set order $asEncountered
  1492.         } else {
  1493.         set order [lsort -ignore [array names $arr]]
  1494.         }
  1495.         foreach f $order {
  1496.         if {[set el [set ${arr}($f)]] != 0} {
  1497.             set next [nextLineStart $el]
  1498.         } else {
  1499.             set next 0
  1500.         } 
  1501.         
  1502.         if { [string first "000" $f] != -1 } {
  1503.             set ff "Class '[set class [lindex $f 0]]'"
  1504.         } elseif { [string first "111" $f] != -1 } {
  1505.             set ff "Namespace '[set class [lindex $f 0]]'"
  1506.         } elseif { [string first "${class}::" $f] == 0 } {
  1507.             set ff [string range $f [string length $class] end]
  1508.         } else {
  1509.             set ff $f
  1510.         }
  1511.         if {$hasMarkers && ![string match "•*" $ff] } {
  1512.             set ff " $ff"
  1513.         } 
  1514.         setNamedMark $ff $el $next $next
  1515.         }
  1516.     }
  1517.     }
  1518. }
  1519.  
  1520. # ◊◊◊◊ Misc. ◊◊◊◊ #
  1521.  
  1522. proc evaluateLine { pos } {
  1523.     goto $pos
  1524.     beginningLineSelect
  1525.     endLineSelect
  1526.  
  1527.     uplevel \#0 evaluate
  1528. }
  1529.  
  1530. tcltk::evaluateRemoteSynchronise
  1531.  
  1532.